package com.jmuok.web.fff.web;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;

import com.jmuok.web.fff.util.ApplicationHelper;
import com.jmuok.web.fff.web.servlet.SpringApplicationServlet;
import com.vaadin.Application;
import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component;
import com.vaadin.ui.Form;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
import com.vaadin.ui.PasswordField;
import com.vaadin.ui.Select;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.themes.Runo;

public class LoginWindow extends Window implements LocaleSelectable {
	private static final long serialVersionUID = 1990971467278569843L;
	private ApplicationHelper helper = ApplicationHelper.instance();
	private static final Log logger = LogFactory.getLog(LoginWindow.class);

	// private Application app;
	@SuppressWarnings("serial")
	public LoginWindow(Application app,
			final AuthenticationManager authenticationManager) {

		setCaption(helper.getMessage("webapp.name"));

		VerticalLayout root = new VerticalLayout();
		setContent(root);
		root.setSizeFull();
		Select localeBox = initLocaleBox(app);
		FormLayout localeLayout = new FormLayout();
		localeLayout.setMargin(false);
		localeLayout.setSpacing(false);
		localeLayout.setSizeUndefined();
		localeLayout.addComponent(localeBox);
		root.addComponent(localeLayout);
		root.setComponentAlignment(localeLayout, Alignment.TOP_RIGHT);

		Label title = new Label(helper.getMessage("webapp.name"));
		title.addStyleName(Runo.LABEL_H1);
		title.setSizeUndefined();
		root.addComponent(title);
		root.setExpandRatio(title, 1);
		root.setComponentAlignment(title, Alignment.BOTTOM_CENTER);

		Label slogan = new Label(helper.getMessage("webapp.slogan"));
		slogan.addStyleName(Runo.LABEL_SMALL);
		slogan.setSizeUndefined();
		root.addComponent(slogan);
		root.setComponentAlignment(slogan, Alignment.BOTTOM_CENTER);

		Label spacer = new Label("");
		spacer.setHeight("20px");
		root.addComponent(spacer);

		final Form form = new Form();
		form.setWidth("75%");
		form.addField("username",
				new TextField(helper.getMessage("label.username")));
		form.addField("password",
				new PasswordField(helper.getMessage("label.password")));
		// form.addField("usergroup", new Select("用户组"));
		form.getField("username").setRequired(true);
		form.getField("username").setWidth("170px");
		form.getField("password").setWidth("170px");
		form.getField("password").setRequired(true);

		// form.getField("usergroup").setWidth("170px");

		VerticalLayout formLayout = new VerticalLayout();
		// formLayout.setSpacing(true);
		// formLayout.setMargin(true);
		formLayout.setSizeFull();
		formLayout.addComponent(form);
		formLayout.setComponentAlignment(form, Alignment.TOP_CENTER);

		Panel login = new Panel(helper.getMessage("login.title"), formLayout);
		login.setSizeUndefined();
		login.setWidth("378px");
		root.addComponent(login);
		root.setComponentAlignment(login, Alignment.TOP_CENTER);
		root.setExpandRatio(login, 1);

		HorizontalLayout buttonLayout = new HorizontalLayout();
		buttonLayout.addStyleName(Runo.LAYOUT_DARKER);
		buttonLayout.setSpacing(true);
		buttonLayout.setWidth("100%");
		buttonLayout.setMargin(true);

		Button ok = new Button(helper.getMessage("button.login") + " »");
		ok.addListener(new Button.ClickListener() {
			public void buttonClick(ClickEvent event) {
				try {
					form.validate();
				} catch (InvalidValueException e) {
					return;
				}
				String un = (String) form.getItemProperty("username")
						.getValue();
				String pass = (String) form.getItemProperty("password")
						.getValue();
				doLogin(un, pass, authenticationManager);

			}

		});

		ok.addStyleName(Runo.BUTTON_BIG);

		Button regist = new Button(helper.getMessage("button.register"),
				new Button.ClickListener() {
					public void buttonClick(ClickEvent event) {
						addWindow(new UserRegWindow());
						// navigator.navigateTo(UserRegView.class);
					}
				});
		regist.addStyleName(Runo.BUTTON_DEFAULT);
		regist.addStyleName(Runo.BUTTON_BIG);

		buttonLayout.addComponent(ok);
		buttonLayout.setComponentAlignment(ok, Alignment.BOTTOM_CENTER);
		buttonLayout.setExpandRatio(ok, 1);
		buttonLayout.addComponent(regist);
		buttonLayout.setExpandRatio(regist, 1);
		buttonLayout.setComponentAlignment(regist, Alignment.BOTTOM_CENTER);

		formLayout.addComponent(new Label("<hr />", Label.CONTENT_XHTML));
		formLayout.addComponent(buttonLayout);

		// root.addComponent(initNavigator());
	}

	@Override
	public Select initLocaleBox(Application app) {
		LocaleBoxComponet localeBox = new LocaleBoxComponet(
				helper.getMessage("label.language"));
		return localeBox.initLocaleBox(app);
	}

	private Authentication doLogin(String un, String pass,
			AuthenticationManager authenticationManager) {
		final Authentication auth = new UsernamePasswordAuthenticationToken(un,
				pass);
		if (logger.isDebugEnabled()) {
			logger.debug("Attempting authentication for user '"
					+ auth.getName() + "'");
		}
		Authentication returned = authenticationManager.authenticate(auth);
		if (logger.isDebugEnabled()) {
			logger.debug("Authentication for user '" + auth.getName()
					+ "' succeeded");
		}
		fireEvent(new LoginEvent(this, returned));
		return returned;
	}

	public static class LoginEvent extends Event {
		private final Authentication authentication;

		public LoginEvent(Component source, Authentication authentication) {
			super(source);
			this.authentication = authentication;
		}

		public Authentication getAuthentication() {
			return authentication;
		}
	}
}
